#include "drv_nvs.h"
#include "drv_rtc.h"
#include "drv_rs485.h"
#include "base_func.h"

static uint8_t s_EventsClean = 0;
uint8_t g_MemSaveErr[2002];
int16_t g_MemSetSchedule[66];

uint16_t nvs_eeprom_data[500];

lv_font_t lv_font_arial_14;
lv_font_t lv_font_arial_16;
lv_font_t lv_font_arial_20;

int nvs_eeprom_to_mem(void)
{
    g_UserSet.Mode = nvs_eeprom_data[1];
    g_UserSet.SetTemp[USER_SET_MODE_WATER] = nvs_eeprom_data[2];

    g_UserSet.BeepEn    = nvs_eeprom_data[90];   
    g_UserSet.BlkMode   = nvs_eeprom_data[91];
    g_UserSet.Lauguage  = nvs_eeprom_data[92];
    g_UserSet.MemoryOn  = nvs_eeprom_data[93]; 
    g_UserSet.WifiEn    = nvs_eeprom_data[94]; 
    g_UserSet.blk_time  = nvs_eeprom_data[95]; 
    g_UserSet.blk_level = nvs_eeprom_data[96]; 
    g_UserSet.password  = nvs_eeprom_data[97]; 
    g_UserSet.unit      = nvs_eeprom_data[98]; 
    
    if(g_UserSet.MemoryOn){
        g_UserSet.f_On = nvs_eeprom_data[0];
        g_UserSet.Updata2CommCnt = 3;
    }
    return 1;
}

int nvs_mem_to_eeprom(void)
{
    int s_change = 0;
    if(nvs_eeprom_data[0] != g_UserSet.f_On){
        nvs_eeprom_data[0] = g_UserSet.f_On;
        s_change++;
    }
    if(nvs_eeprom_data[1] != g_UserSet.Mode){
        nvs_eeprom_data[1] = g_UserSet.Mode;
        s_change++;
    }
    if(nvs_eeprom_data[2] != g_UserSet.SetTemp[USER_SET_MODE_WATER]){
        nvs_eeprom_data[2] = g_UserSet.SetTemp[USER_SET_MODE_WATER];
        s_change++;
    }

    if(g_UserSet.BeepEn != nvs_eeprom_data[90]){
        nvs_eeprom_data[90] = g_UserSet.BeepEn;
        s_change++;
    }
    if(g_UserSet.BlkMode != nvs_eeprom_data[91]){
        nvs_eeprom_data[91] = g_UserSet.BlkMode;
        s_change++;
    }
    if(g_UserSet.Lauguage != nvs_eeprom_data[92]){
        nvs_eeprom_data[92] = g_UserSet.Lauguage;
        s_change++;
    }
    if(g_UserSet.MemoryOn != nvs_eeprom_data[93]){
        nvs_eeprom_data[93] = g_UserSet.MemoryOn;
        s_change++;
    }
    if(g_UserSet.WifiEn != nvs_eeprom_data[94]){
        nvs_eeprom_data[94] = g_UserSet.WifiEn;
        s_change++;
    }
    if(g_UserSet.blk_time != nvs_eeprom_data[95]){
        nvs_eeprom_data[95] = g_UserSet.blk_time;
        s_change++;
    }
    if(g_UserSet.blk_level != nvs_eeprom_data[96]){
        nvs_eeprom_data[96] = g_UserSet.blk_level;
        s_change++;
    }
    if(g_UserSet.password != nvs_eeprom_data[97]){
        nvs_eeprom_data[97] = g_UserSet.password;
        s_change++;
    }
    if(g_UserSet.unit != nvs_eeprom_data[98]){
        nvs_eeprom_data[98] = g_UserSet.unit;
        s_change++;
    }

    return s_change;
}

char *fun_FindErrorString(uint16_t error_code)
{
    static char error_string[20];
    if((error_code)&&(error_code !=( '0'*256))){
        sprintf(error_string, "%c%02d", (error_code >> 8) & 0xFF, (error_code & 0xFF));
        return error_string;
    }
    return NULL;
}

void fun_ErrSaveCheck(void)
{
    int err = 0;
    uint8_t tmp_HasNewErr = 0;
    uint16_t tmp_CopyCnt = 0;
    static char *s_ErrorCode = NULL, *error_code = NULL;

    error_code = fun_FindErrorString(g_UserSet.ErrorCode);
    if((s_ErrorCode != error_code) && error_code){
        tmp_HasNewErr ++;
        tmp_CopyCnt = 1599;
        while( tmp_CopyCnt >= 8 ){
            g_MemSaveErr[tmp_CopyCnt] = g_MemSaveErr[tmp_CopyCnt - 8];
            tmp_CopyCnt--;
        }
        g_MemSaveErr[0] = (g_UserSet.ErrorCode >> 8) & 0xFF;
        g_MemSaveErr[1] = (g_UserSet.ErrorCode >> 0) & 0xFF;
        g_MemSaveErr[2] = g_CurrentRTC.Second;                     
        g_MemSaveErr[3] = g_CurrentRTC.Minute;                     
        g_MemSaveErr[4] = g_CurrentRTC.Hour;                       
        g_MemSaveErr[5] = g_CurrentRTC.Day;                        
        g_MemSaveErr[6] = g_CurrentRTC.Month;                      
        g_MemSaveErr[7] = g_CurrentRTC.Year;
    }
    s_ErrorCode = error_code;

    if( tmp_HasNewErr || s_EventsClean ){
        s_EventsClean = 0;
        err = nvs_write_data("events", g_MemSaveErr, sizeof(g_MemSaveErr));
        printf("events nvs write [%d] ...", err);
    }
}

void *thread_nvs_scan(void *argc)
{
    int err;
    size_t len = 0;

    g_UserSet.BlkTimer = 120;

    nvs_eeprom_data[0] = 0;      //开关机
    nvs_eeprom_data[1] = 1;      //模式
    nvs_eeprom_data[2] = 400;    //水箱设定温度

    nvs_eeprom_data[90] = 1;    //蜂鸣器开关
    nvs_eeprom_data[91] = 0;    //背光模式
    nvs_eeprom_data[92] = 0;    //语言
    nvs_eeprom_data[93] = 0;    //开关机记忆
    nvs_eeprom_data[94] = 1;    //wifi使能开关
    nvs_eeprom_data[96] = 80;   //背光亮度
    nvs_eeprom_data[97] = 2345; //默认密码
    nvs_eeprom_data[98] = 0;    //温度单位

    for (len = 0; len < 8; len++){
        g_MemSetSchedule[len * 6 + 0] = 0x7F;
        g_MemSetSchedule[len * 6 + 1] = 0x01;
        g_MemSetSchedule[len * 6 + 2] = 0x01;
        g_MemSetSchedule[len * 6 + 3] = 25;
        g_MemSetSchedule[len * 6 + 4] = 18;
        g_MemSetSchedule[len * 6 + 5] = 0;
    }

    len = sizeof(g_MemSetSchedule);
    err = nvs_read_data("schedule", g_MemSetSchedule, &len);
    printf("schedule nvs read [%d] ...\r\n", err);
    if(err != 0){
        err = nvs_write_data("schedule", g_MemSetSchedule, sizeof(g_MemSetSchedule));
        printf("schedule nvs write [%d] ...\r\n", err);
    }

    len = sizeof(nvs_eeprom_data);
    err = nvs_read_data("eeprom", nvs_eeprom_data, &len);
    printf("eeprom nvs read [%d] ...\r\n", err);
    if(err != 0){
        err = nvs_write_data("eeprom", nvs_eeprom_data, sizeof(nvs_eeprom_data));
        printf("eeprom nvs write [%d] ...\r\n", err);
    }
    nvs_eeprom_to_mem();

    len = sizeof(g_MemSaveErr);
    err = nvs_read_data("events", g_MemSaveErr, &len);
    printf("events nvs read [%d] ...\r\n", err);
    if(err != 0){
        err = nvs_write_data("events", g_MemSaveErr, sizeof(g_MemSaveErr));
        printf("events nvs write [%d] ...\r\n", err);
    }
    if(g_UserSet.blk_level < 0){
        g_UserSet.blk_level = 0;
    }
    if(g_UserSet.blk_time <= 1){
		g_UserSet.blk_time = 1;
	}
    while (1){
        if(g_UserSet.SchedNvs){
            g_UserSet.SchedNvs = 0;
            err = nvs_write_data("schedule", g_MemSetSchedule, sizeof(g_MemSetSchedule));
            printf("schedule nvs write [%d] ...\r\n", err);
        }
        if(nvs_mem_to_eeprom() > 0){
            err = nvs_write_data("eeprom", nvs_eeprom_data, sizeof(nvs_eeprom_data));
            printf("eeprom nvs write [%d] ...\r\n", err);
        }

        fun_ErrSaveCheck();
        sleep(2);
    }
}

void set_temp_limit(void)
{
    g_UserSet.SetTempMin[USER_SET_MODE_AUTO]        = 100;
    g_UserSet.SetTempMin[USER_SET_MODE_COOL]        = 100;
    g_UserSet.SetTempMin[USER_SET_MODE_HEAT]        = 150;
    g_UserSet.SetTempMin[USER_SET_MODE_WATER]       = 100;
    g_UserSet.SetTempMax[USER_SET_MODE_AUTO]        = 600;
    g_UserSet.SetTempMax[USER_SET_MODE_COOL]        = 300;
    g_UserSet.SetTempMax[USER_SET_MODE_HEAT]        = 600;
    g_UserSet.SetTempMax[USER_SET_MODE_WATER]       = 600;
}

int nvs_start(void)
{
    int res = 0;
    pthread_t tid_nvs_scan;

    g_UserSet.Mode = USER_SET_MODE_COOL;
    g_UserSet.SetTemp[USER_SET_MODE_AUTO]           = 260;
    g_UserSet.SetTemp[USER_SET_MODE_COOL]           = 200;
    g_UserSet.SetTemp[USER_SET_MODE_HEAT]           = 400;
    g_UserSet.SetTemp[USER_SET_MODE_WATER]          = 400;
    g_UserSet.SetTemp[USER_SET_MODE_WATER_COOL]     = 400;
    g_UserSet.SetTemp[USER_SET_MODE_WATER_HEAT]     = 400;
    g_UserSet.SetTemp[USER_SET_MODE_FAN]            = 250;
    g_UserSet.SetTemp[USER_SET_MODE_DRY]            = 250;
    g_UserSet.SetTemp[USER_SET_MODE_SPA]            = 260;

    g_UserSet.SysID = 0;
    set_temp_limit();

    res = pthread_create(&tid_nvs_scan , NULL , thread_nvs_scan , NULL);
    if(res){
        perror("thread_nvs_scan creat error!\r\n");
    }
    return 0;
}

int nvs_read_data(const char* key, void* out_value, size_t* length)
{
    struct stat sta; 
    int setup_fd, ret;

    printf("nvs_read_data [%s]... \r\n", key);
    setup_fd = open(key, O_RDONLY);
    if(setup_fd < 0){
        return -1;
    }else{
        stat(key, &sta);
        if(sta.st_size != *length){
            printf("sta.st_size != length ...\r\n");
            return -1;
        }
        printf("file is exist, read file [%d]...\r\n", setup_fd);
        ret = (int)read(setup_fd, out_value, *length);
        if(ret > 0){
            printf("read file success, read file [%d]...\r\n", ret);
        }else{
            printf("read file filed, error [%d]...\r\n", ret);
        }
        close(setup_fd);
        return 0;
    }
}

int nvs_write_data(const char* key, const void* value, size_t length)
{
    int setup_fd, ret;

    setup_fd = open(key, O_RDWR | O_CREAT, 0777);
    if(setup_fd < 0){
        printf("open file [%s] error ...\r\n", key);
        return -1;
    }else{
        printf("open file [%s] success ...\r\n", key);
        ret = (int)write(setup_fd, value, length);
        if(ret > 0){
            printf("write file success, writed [%d] bytes...\r\n", ret);
        }else{
            printf("write file filed, error [%d]...\r\n", ret);
        }
        close(setup_fd);
        system("sync");
        return 0;
    }
    system("sync");
}


void write_new_firmware(uint8_t *data, uint32_t length)
{
    int setup_fd, ret;
    setup_fd = open("/root/new_firmware.bin", O_RDWR | O_CREAT, 0777);
    if(setup_fd < 0){
        printf("open new_firmware error, [%d]...\r\n", setup_fd);
    }else{
        printf("open new_firmware success, filefd is [%d]...\r\n", setup_fd);
        ret = (int)write(setup_fd, data,length);
        if(ret > 0){
            printf("write new_firmware success, writed [%d] bytes...\r\n", ret);
        }else{
            printf("write new_firmware filed, error [%d]...\r\n", ret);
        }
        close(setup_fd);
    }
    system("chmod +x /root/new_firmware.bin");
    system("sync");
}

int nvs_events_clean(void)
{
    s_EventsClean = 1;
    memset(g_MemSaveErr, 0, sizeof(g_MemSaveErr));
    return 0;
}

